/*
 * WebQuery.java
 *
 * Created on March 10, 2005, 2:08 PM
 */
package web;


import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import org.w3c.dom.*;
import java.util.*;
import xml.XMLHelper;


/**
 *
 * @author Keith
 */
public class WebQuery {

  /**
   * Holds value of property urlGenerator.
   */
  final private Document urlGenerator;
  /**
   * Holds value of property xmlGenerator.
   */
  final private Document xmlGenerator;
  /**
   * Holds value of property webSite.
   */
  final private WebSite webSite;
  final private List<WebQueryInstance> queryList = new ArrayList<WebQueryInstance>();
  private File output;


  /** Creates a new instance of WebQuery
   * @param website
   * @param ug
   * @param xg
   * @param output 
   */
  public WebQuery( WebSite website, Document ug, Document xg, File output ) {
    this.webSite = website;
    urlGenerator = ug;
    xmlGenerator = xg;
    this.output = output;
  }


  /**
   * Getter for property urlGenerator.
   * @return Value of property urlGenerator.
   */
  public Document getUrlGenerator() {

    return urlGenerator;
  }


  /**
   * Getter for property xmlGenerator.
   * @return Value of property xmlGenerator.
   */
  public Document getXmlGenerator() {

    return xmlGenerator;
  }


  /**
   * Getter for property webSite.
   * @return Value of property webSite.
   */
  public WebSite getWebSite() {
    return this.webSite;
  }


  public File getOutput() {
    return output;
  }


  /**
   * Returns a string representation of the object. In general, the 
   * <code>toString</code> method returns a string that 
   * "textually represents" this object. The result should 
   * be a concise but informative representation that is easy for a 
   * person to read.
   * It is recommended that all subclasses override this method.
   * <p>
   * The <code>toString</code> method for class <code>Object</code> 
   * returns a string consisting of the name of the class of which the 
   * object is an instance, the at-sign character `<code>@</code>', and 
   * the unsigned hexadecimal representation of the hash code of the 
   * object. In other words, this method returns a string equal to the 
   * value of:
   * <blockquote>
   * <pre>
   * getClass().getName() + '@' + Integer.toHexString(hashCode())
   * </pre></blockquote>
   * 
   * @return  a string representation of the object.
   */
  @Override
  public String toString() {
    final String lineSep = System.getProperty( "line.separator" );
    StringBuffer sb = new StringBuffer( "[" );

    sb.append( lineSep );
    sb.append( "urlGenerator: [" );
    sb.append( XMLHelper.asString( urlGenerator ) );
    sb.append( "]" );
    sb.append( lineSep );
    sb.append( "xmlGenerator: [" );
    sb.append( XMLHelper.asString( xmlGenerator ) );
    sb.append( "]" );
    sb.append( "]" );

    return sb.toString();
  }


  static protected Set<String> extractURL( Properties params, Document urlGenDOM ) {
    Set<String> dataUrl = new HashSet<String>();
    DOMResult result = new DOMResult();

    try {
      Transformer transformer = XMLHelper.getTransformer( new DOMSource(
                                                          urlGenDOM ) );

      transformer.clearParameters();
      if ( params != null ) {
        for ( String paramName : params.stringPropertyNames() ) {
          transformer.setParameter( paramName, params.getProperty( paramName ) );
        }
      }
      transformer.transform( new DOMSource( urlGenDOM ), result );
      /*
      dom.Writer writer = new dom.Writer();
      writer.setOutput( System.out, null );
      writer.write( dom.getNode() );
       */
      org.w3c.dom.Document outDoc = (org.w3c.dom.Document) result.getNode();
      org.w3c.dom.NodeList nl = outDoc.getElementsByTagName( "path" );

      for ( int idx = 0, len = nl.getLength(); idx < len; idx++ ) {
        Node urlNode = nl.item( idx );
        org.w3c.dom.NodeList children = urlNode.getChildNodes();

        dataUrl.add( XMLHelper.getNodeValue( children ) );
      }
    } catch ( TransformerConfigurationException ex ) {
      ex.printStackTrace();
    } catch ( TransformerException ex ) {
      ex.printStackTrace();
    }

    return dataUrl;
  }


  public Set<URL> getURL( Properties params ) throws MalformedURLException {
    Set<String> stringSet = extractURL( params, getUrlGenerator() );
    Set<URL> urlSet = new HashSet<URL>( stringSet.size() );

    for ( String s : stringSet ) {
      urlSet.add( new URL( webSite.getHost(), s ) );
    }
    return urlSet;
  }


  public void add( WebQueryInstance webQueryInstance ) {
    queryList.add( webQueryInstance );
  }


  public List<WebQueryInstance> getQueryList() {
    return Collections.unmodifiableList( queryList );
  }


  public int querySuccessCount() {
    int successCnt = 0;

    for ( WebQueryInstance wqi : queryList ) {
      if ( wqi.isQuerySuccess() ) {
        successCnt++;
      }
    }

    return successCnt;
  }


  public int queryFailureCount() {
    return queryList.size() - querySuccessCount();
  }
}
